/**
 * 
 */
package anyware.desktop.impl;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;

import javax.annotation.Resource;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.Validate;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.NumberTools;
import org.apache.lucene.document.Field.Index;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.store.Directory;
import org.apache.tika.config.TikaConfig;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.Parser;
import org.apache.tika.sax.WriteOutContentHandler;
import org.apache.tika.utils.ParseUtils;
import org.springframework.stereotype.Service;
import org.xml.sax.SAXException;

import anyware.common.io.DeleteWhenCloseFileInputStream;
import anyware.desktop.IndexException;
import anyware.desktop.IndexService;
import anyware.desktop.model.FileItem;

/**
 * @author keke
 * 
 */
@Service("indexService")
public class DefaultIndexService implements IndexService {
    private Directory             directory;
    private transient IndexWriter indexWriter;
    private Analyzer              analyzer;
    private TikaConfig            tikaConfig;

    public void commitIndex() throws IOException {
        indexWriter.flush();
        indexWriter.close();
        indexWriter = null;
    }

    public void index(final FileItem item) throws IOException, IndexException {
        Validate.notNull(item);
        try {
            final Parser parser = ParseUtils.getParser(item.getFile(),
                    tikaConfig);
            if (parser != null) {
                final Metadata metadata = new Metadata();
                final File temp = File.createTempFile("desktop", "indextemp");
                final WriteOutContentHandler handler = new WriteOutContentHandler(
                        new FileWriter(temp));
                parser.parse(new FileInputStream(item.getFile()), handler,
                        metadata);

                final Document doc = new Document();
                doc.add(new Field("id", NumberTools.longToString(item.getId()),
                        Store.YES, Index.UN_TOKENIZED));
                doc.add(new Field("name", FilenameUtils.getBaseName(item
                        .getName()), Store.YES, Index.TOKENIZED));
                doc.add(new Field("type", FilenameUtils.getExtension(item
                        .getName()), Store.YES, Index.UN_TOKENIZED));
                doc.add(new Field("content", new BufferedReader(
                        new InputStreamReader(
                                new DeleteWhenCloseFileInputStream(item
                                        .getFile())))));
                indexWriter.addDocument(doc);
            }
        } catch (final TikaException e) {
            throw new IndexException(e);
        } catch (final SAXException e) {
            throw new IndexException(e);
        }

    }

    @Resource(name="luceneDir")
    public void setDirectory(final Directory directory) {
        this.directory = directory;
    }

    public void startIndex() throws IOException {
        final boolean exist = IndexReader.indexExists(directory);
        if (exist && IndexReader.isLocked(directory)) {
            IndexReader.unlock(directory);
        }
        // create index if not existed;
        indexWriter = new IndexWriter(directory, analyzer, !exist);
    }
}
